home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / DevCon / Atlanta_1990 / Atlanta-Devcon.1 / Libraries / Intuition / boopsi / mymodelclass.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-26  |  7.0 KB  |  298 lines

  1. /* mymodelclass.c -- :ts=8
  2.  * Example of a simple subclass of "modelclass".
  3.  * It maintains an integer "current value", which
  4.  * it keeps between 0 and some specified maximum.
  5.  */
  6.  
  7. /*
  8. Copyright (c) 1989, 1990 Commodore-Amiga, Inc.
  9.  
  10. Executables based on this information may be used in software
  11. for Commodore Amiga computers. All other rights reserved.
  12. This information is provided "as is"; no warranties are made.
  13. All use is at your own risk, and no liability or responsibility
  14. is assumed.
  15. */
  16.  
  17. #include "sysall.h"
  18. #include <intuition/classes.h>
  19. #include "mymodel.h"        /* attributes are defined there    */
  20.  
  21. #ifdef printf
  22. #undef printf
  23. #endif
  24.  
  25. #define printf kprintf
  26.  
  27.  
  28. #define D(x)    ;
  29.  
  30. /* private class    */
  31. #define MYCLASSID    (NULL)
  32. extern struct Library    *IntuitionBase;
  33. #define SUPERCLASSID    MODELCLASS
  34.  
  35. struct MyModData    {
  36.     ULONG    mmd_CurrentValue;
  37.     ULONG    mmd_Range;        /* current value <= range-1    */
  38. };
  39.  
  40. Class    *
  41. initMyModClass()
  42. {
  43.     ULONG __saveds    dispatchMyMod();
  44.     ULONG    hookEntry();
  45.     Class    *cl;
  46.     Class    *MakeClass();
  47.  
  48.     if ( cl =  MakeClass( MYCLASSID, 
  49.         SUPERCLASSID, NULL,        /* superclass is public      */
  50.          sizeof ( struct MyModData ),
  51.         0 ))
  52.     {
  53.     /* initialize the cl_Dispatcher Hook    */
  54.     cl->cl_Dispatcher.h_Entry = hookEntry;
  55.     cl->cl_Dispatcher.h_SubEntry = dispatchMyMod;
  56.     cl->cl_Dispatcher.h_Data = (VOID *) 0xFACE;    /* unused */
  57.     }
  58.     return ( cl );
  59. }
  60.  
  61. freeMyModClass( cl )
  62. Class    *cl;
  63. {
  64.     return ( FreeClass( cl )  );
  65. }
  66.  
  67. ULONG __saveds 
  68. dispatchMyMod( cl, o, msg )
  69. Class   *cl;
  70. Object  *o;
  71. Msg     msg;
  72. {
  73.     Object    *newobj;
  74.     ULONG    oldval;
  75.     ULONG    oldrng;
  76.     ULONG    notify_msg_flags = 0;
  77.     ULONG    interim_flag;
  78.  
  79.     struct MyModData    *mmd;
  80.  
  81.     D( printf("mymodel dispatcher, method ID %lx\n", msg->MethodID ) );
  82.  
  83.     mmd = INST_DATA( cl, o );
  84.  
  85.     switch ( msg->MethodID )
  86.     {
  87.     /* use superclass defaults for everything else */
  88.     case OM_NEW:
  89.     D( printf("mymodel: OM_NEW\n") );
  90.     if( newobj = (Object *) DSM( cl, o, msg ) )
  91.     {
  92.         D( printf("new model object at %lx\n", newobj ) );
  93.         /* initialize instance data (they start life as 0)    */
  94.         setMyModAttrs( cl, newobj, msg );
  95.     }
  96.     return ( (ULONG) newobj );
  97.  
  98.     case OM_GET:
  99.     return ( (ULONG) getMyModAttr( cl, o, msg ) );
  100.  
  101.     case OM_SET:
  102.     case OM_UPDATE:
  103.     D( printf("mymod update\n" ) );
  104.     if ( ! DoSuperMethod( cl, o, ICM_CHECKLOOP ) ) 
  105.     {
  106.         /* let the superclass see whatever it wants from OM_SET,
  107.          * such as ICA_TARGET, ICA_MAP, and so on.  For OM_NOTIFY,
  108.          * however, we control all traffic and issue notification
  109.          * specifically for the attributes we're interested in.
  110.          */
  111.         if ( msg->MethodID == OM_SET )
  112.         {
  113.         D( printf("mymod update is actually OM_SET\n"));
  114.         DSM( cl, o, msg );
  115.         }
  116.         else
  117.         {
  118.         /* these flags aren't present in the message of OM_SET    */
  119.         notify_msg_flags =  ((struct opUpdate *)msg)->opu_Flags;
  120.         }
  121.  
  122.         /*
  123.          * I'll be wanting to know this is an "interim" message
  124.          * or a final report (which I always want to send, even
  125.          * if the value of mmd_CurrentValue hasn't changed).
  126.          */
  127.         interim_flag =  notify_msg_flags & OPUF_INTERIM;
  128.  
  129.         /* Now set possibly new value of mmd_CurrentVal, and
  130.          * maybe a range change.
  131.          * Only send a notification message along for values of
  132.          * interest that have changed.
  133.          */
  134.  
  135.         /* save 'em    */
  136.         oldval = mmd->mmd_CurrentValue;
  137.         oldrng = mmd->mmd_Range;
  138.  
  139.         /* change 'em, only if changed (or if
  140.          * a "non-interim" message.
  141.          */
  142.         if ( setMyModAttrs( cl, o, msg ) || ! interim_flag )
  143.         {
  144.             Tag    rangetag;
  145.             Tag    currvaltag;
  146.  
  147. /* if condition is false, replace tag with TAG_IGNORE    */
  148. #define XTAG( expr, tagid ) ((expr)? (tagid): TAG_IGNORE)
  149.  
  150.         rangetag = (oldrng!=mmd->mmd_Range)? MYMODA_RANGE: TAG_IGNORE;
  151.         if ( ! interim_flag || (oldval != mmd->mmd_CurrentValue) )
  152.         {
  153.             currvaltag = MYMODA_CURRVAL;
  154.         }
  155.         else
  156.         {
  157.             currvaltag = TAG_IGNORE;
  158.         }
  159.  
  160.  
  161.         D( printf("mymod: sending notification\n") );
  162.  
  163.         /* Pass along GInfo, if any, so gadgets can redraw
  164.          * themselves.  Pass along opu_Flags, so that the
  165.          * application will know the difference between
  166.          * and interim message and a final message
  167.          */
  168.         notifyAttrChanges( o, ((struct opSet *)msg)->ops_GInfo,
  169.             interim_flag,
  170.             rangetag,    mmd->mmd_Range,
  171.             currvaltag,    mmd->mmd_CurrentValue,
  172.             TAG_END );
  173.         }
  174.         D( else printf("setMyModAttrs returnes 'nochange'\n"));
  175.     }
  176.     D( else printf("Loop Check violation!\n"));
  177.     break;
  178.  
  179.     case OM_NOTIFY:
  180.         D( printf("mymod: forwarding OM_NOTIFY to superclass modelclass\n"));
  181.     case OM_DISPOSE:
  182.     default:
  183.     D( printf("let superclass handle it\n"));
  184.     return ( (ULONG) DSM( cl, o, msg ) );
  185.     }
  186.     return ( 1 );
  187. }
  188.  
  189. setMyModAttrs( cl, o, msg )
  190. Class        *cl;
  191. Object        *o;
  192. struct opSet    *msg;
  193. {
  194.     struct TagItem    *tags = msg->ops_AttrList;
  195.     struct MyModData    *mmd;
  196.     int            changes = FALSE;
  197.     LONG        newval;
  198.     ULONG        newrng;
  199.  
  200.     mmd = INST_DATA( cl, o );
  201.  
  202.     D( printf("setMyModAttrs, object %lx\n", o ) );
  203.     D( dumpTagList( "mymod attr tags", tags ));
  204.  
  205.     newrng =  GetTagData( MYMODA_RANGE, mmd->mmd_Range, tags );
  206.  
  207.     if ( mmd->mmd_Range != newrng )
  208.     {
  209.     D( printf( "mymod: range has changed value to %ld\n",
  210.         mmd->mmd_Range ));
  211.     mmd->mmd_Range =  newrng;
  212.     changes = TRUE;
  213.     }
  214.  
  215.     /* validity check    */
  216.     if ( mmd->mmd_Range == 0 )
  217.     {
  218.     mmd->mmd_Range = 1;
  219.     changes = TRUE;
  220.     }
  221.  
  222.     D( printf("range is %ld\n", mmd->mmd_Range ) );
  223.  
  224.     /* start with original value    */
  225.     newval =  mmd->mmd_CurrentValue;
  226.  
  227.     D( printf("original currval %ld\n", mmd->mmd_CurrentValue ) );
  228.  
  229.     /* increment/decrement in response to strobes    */
  230.     if ( GetTagData( MYMODA_INCRSTROBE, 0, tags ) > 0 )
  231.     {
  232.     newval++;
  233.     D( printf("strobe increment newval to %ld\n", newval ) );
  234.     }
  235.     if ( GetTagData( MYMODA_DECRSTROBE, FALSE, tags ) > 0 )
  236.     {
  237.     if ( newval > 0 ) newval--;
  238.     D( printf("strobe decrement newval to %ld\n", newval ) );
  239.     }
  240.  
  241.     /* look at "absolute" setting last    */
  242.     newval = GetTagData( MYMODA_CURRVAL, newval, tags );
  243.  
  244.     D( printf("unconstrained newval %ld\n", newval ) );
  245.  
  246.     /* limit mmd_CurrentValue to mmd_Range-1    */
  247.     if ( newval < 0 ) newval = 0;
  248.     if ( newval > (mmd->mmd_Range-1) ) newval = mmd->mmd_Range - 1;
  249.  
  250.     D( printf( "final: new current value %ld\n", newval ));
  251.  
  252.     if ( mmd->mmd_CurrentValue != newval )
  253.     {
  254.         mmd->mmd_CurrentValue = newval;
  255.     D( printf( "mymod: value has changed to %ld\n",
  256.         mmd->mmd_CurrentValue ));
  257.     changes = TRUE;
  258.     }
  259.  
  260.     return ( changes );
  261. }
  262.  
  263. getMyModAttr( cl, o, msg )
  264. Class        *cl;
  265. Object        *o;
  266. struct opGet    *msg;
  267. {
  268.     struct MyModData    *mmd;
  269.  
  270.     mmd = INST_DATA( cl, o );
  271.  
  272.     switch ( msg->opg_AttrID )
  273.     {
  274.     case MYMODA_CURRVAL:
  275.     *msg->opg_Storage = mmd->mmd_CurrentValue;
  276.     break;
  277.     case MYMODA_RANGE:
  278.     *msg->opg_Storage = mmd->mmd_Range;
  279.     break;
  280.     default:
  281.     /* I don't recognize this one, let the superclass try    */
  282.     return ( DSM( cl, o, msg ) );
  283.     }
  284.     return ( TRUE );
  285. }
  286.  
  287. /*
  288.  * a convenient way to construct and send an OM_NOTIFY message
  289.  */
  290. notifyAttrChanges( o, ginfo, flags, tag1 )
  291. Object    *o;
  292. void    *ginfo;
  293. ULONG    flags;
  294. ULONG    tag1;
  295. {
  296.     return ( DoMethod( o, OM_NOTIFY, &tag1, ginfo, flags ) );
  297. }
  298.